package viid

import (
	"strconv"
	"strings"
	"time"
)

type (
	DeviceIDType         string // string(20) GA/T 1400.1，采集设备、卡口点位、采集系统、分析系统、视图库、应用平台等设备编码规则 34078100 00 119 0 001002
	BasicObjectIdType    string // string(41) GA/T 1400.1，图像信息基本要素 ID，视频、图像、文件 34078100 00 119 0 001002 03 20240214121314 00001
	ImageCntObjectIdType string // string(48) GA/T 1400.1 图像信息内容要素 ID，人、人脸、机动车、非机动车、物品、场景等 34078100 00 119 0 001002 03 20240214121314 00001 06 00001

	CaseObjectIdType     = string // string(30) GA/T 1400.1，案(事)件管理对象 ID
	BusinessObjectIdType = string // string(33) GA/T 1400.1，布控、订阅及相应通知 管理对象 ID  650100010000 04 20170401120101 00001

	PlaceCodeType = string // string(6) GB/T 2260 行政区划、籍贯省市县代码
	OrgCodeType   = string // string(12) 机构代码(由 GA/T 380 规定)

	DeviceNameType = string // DeviceNameType string(0..100) 设备名称
	ModelType      = string // ModelType string(0..100) 设备型号
	KeywordType    = string // KeywordType string(0..200 关键词
	IPAddrType     = string // IPAddrType string(0..30) IP地址
	IPV6AddrType   = string // IPV6AddrType string(64) IPv6地址
	NetPortType    = int    // NetPortType 网络端口号

	PasswordType = string // string(00..32) 口令

	PlaceFullAddressType = string // string(100) GA/T 543.1， 具体到摄像机位置或街道门牌号， 由 DE00072( 乡 镇 街 道 )+DE00074( 街 路 巷 )+ DE00080( 门 楼 牌号)+ DE00081(门楼详细地址)构成

	NameType = string // string(0..50) DE00002 姓名
	OrgType  = string // string(0..100) DE00065 单位名称

	FileNameType = string // string(0..256) DE01070 电子文件名

	SpeedType = float64 // SpeedType 速度

	PlateNoType = string // PlateNoType 机动车号牌号码 string(0..15)

	LongitudeType = float64 // 地球经度 n10， 6;精确到小数点后 6 位
	LatitudeType  = float64 // 地球纬度 n10， 6;精确到小数点后 6 位
)

type StatusCode int

const (
	StatusCodeOK                 = 0 // 正常
	StatusCodeOtherError         = 1 // 其他未知错误
	StatusCodeDeviceBusy         = 2 // 设备忙
	StatusCodeDeviceError        = 3 // 设备错误
	StatusCodeInvalidOperation   = 4 // 无效操作
	StatusCodeInvalidXMLFormat   = 5 // XML 格式无效
	StatusCodeInvalidXMLContent  = 6 // XML 内容无效
	StatusCodeInvalidJSONFormat  = 7 // JSON 格式无效
	StatusCodeInvalidJSONContent = 8 // JSON 内容无效
	StatusCodeReboot             = 9 // 系统重启中，以附录 B 中类型定义为准
)

type InfoType int

const (
	InfoTypeOther  InfoType = 0
	InfoTypeAuto   InfoType = 1
	InfoTypeManual InfoType = 2
)

type BoolType int

const (
	BoolTypeFalse   = 0
	BoolTypeTrue    = 1
	BoolTypeNotSure = 2
)

type GenderType string

const (
	GenderTypeUnknown GenderType = "0" // 未知的性别
	GenderTypeM       GenderType = "1" // 男性
	GenderTypeF       GenderType = "2" // 女性
	GenderTypeNotSure GenderType = "9" // 未说明的性别
)

// PersonStatusType 人的状态
type PersonStatusType string

const (
	PersonStatusType1  PersonStatusType = "1"  // 醉酒
	PersonStatusType2  PersonStatusType = "2"  // 亢奋
	PersonStatusType3  PersonStatusType = "3"  // 正常
	PersonStatusType99 PersonStatusType = "99" // 其它
)

// PostureType 姿态
type PostureType string

const (
	PostureType1  PostureType = "1"  // 站
	PostureType2  PostureType = "2"  // 蹲
	PostureType3  PostureType = "3"  // 卧
	PostureType4  PostureType = "4"  // 躺
	PostureType5  PostureType = "5"  // 坐
	PostureType6  PostureType = "6"  // 行走
	PostureType7  PostureType = "7"  // 奔跑
	PostureType8  PostureType = "8"  // 跳跃
	PostureType9  PostureType = "9"  // 攀登
	PostureType10 PostureType = "10" // 匍匐
	PostureType99 PostureType = "99" // 其它
)

type ColorType string

const (
	ColorType1  ColorType = "1"  // 黑
	ColorType2  ColorType = "2"  // 白
	ColorType3  ColorType = "3"  // 灰
	ColorType4  ColorType = "4"  // 红
	ColorType5  ColorType = "5"  // 蓝
	ColorType6  ColorType = "6"  // 黄
	ColorType7  ColorType = "7"  // 橙
	ColorType8  ColorType = "8"  // 棕
	ColorType9  ColorType = "9"  // 绿
	ColorType10 ColorType = "10" // 紫
	ColorType11 ColorType = "11" // 青
	ColorType12 ColorType = "12" // 粉
	ColorType13 ColorType = "13" // 透明
	ColorType99 ColorType = "99" // 其它
)

type DateTime string

func NewDateTime(t time.Time) DateTime {
	var v DateTime
	v.SetTime(t)
	return v
}

func (c *DateTime) GetTime() time.Time {
	if c == nil {
		return time.Time{}
	}

	// 20240306114320
	if t, err := time.Parse("20060102150405", string(*c)); err != nil {
		return time.Time{}
	} else {
		return t
	}
}

func (c *DateTime) SetTime(t time.Time) *DateTime {
	if c == nil {
		return c
	}

	*c = DateTime(t.Format("20060102150405"))

	return c
}

type (
	SubscribeDetailTypeItem string
	SubscribeDetailType     []SubscribeDetailTypeItem
)

func (c SubscribeDetailType) MarshalJSON() ([]byte, error) {

	var item []string
	for _, o := range c {
		item = append(item, string(o))
	}

	value := "\"" + strings.Join(item, ",") + "\""

	return []byte(value), nil
}

func (c *SubscribeDetailType) UnmarshalJSON(data []byte) error {
	if data == nil {
		return nil
	}

	str := string(data)
	if len(str) >= 2 {
		str = str[1 : len(str)-1]
	}

	parts := strings.Split(str, ",")
	for _, part := range parts {
		part = strings.TrimSpace(part)
		if len(part) > 0 {
			*c = append(*c, SubscribeDetailTypeItem(part))
		}
	}
	return nil
}

func (c SubscribeDetailTypeItem) Value() (int, bool) {
	value, err := strconv.ParseInt(string(c), 10, 32)
	if err != nil {
		return 0, false
	}
	if value >= 1 && value <= 16 {
		return int(value), true
	}

	return 0, false
}

const (
	SubscribeDetailTypeItem1  SubscribeDetailTypeItem = "1"  // 案(事)件目录
	SubscribeDetailTypeItem2  SubscribeDetailTypeItem = "2"  // 单个案(事)件内容
	SubscribeDetailTypeItem3  SubscribeDetailTypeItem = "3"  // 采集设备目录
	SubscribeDetailTypeItem4  SubscribeDetailTypeItem = "4"  // 采集设备状态
	SubscribeDetailTypeItem5  SubscribeDetailTypeItem = "5"  // 采集系统目录
	SubscribeDetailTypeItem6  SubscribeDetailTypeItem = "6"  // 采集系统状态
	SubscribeDetailTypeItem7  SubscribeDetailTypeItem = "7"  // 视频卡口目录
	SubscribeDetailTypeItem8  SubscribeDetailTypeItem = "8"  // 单个卡口记录
	SubscribeDetailTypeItem9  SubscribeDetailTypeItem = "9"  // 车道目录
	SubscribeDetailTypeItem10 SubscribeDetailTypeItem = "10" // 单个车道记录
	SubscribeDetailTypeItem11 SubscribeDetailTypeItem = "11" // 自动采集的人员信息
	SubscribeDetailTypeItem12 SubscribeDetailTypeItem = "12" // 自动采集的人脸信息
	SubscribeDetailTypeItem13 SubscribeDetailTypeItem = "13" // 自动采集的车辆信息
	SubscribeDetailTypeItem14 SubscribeDetailTypeItem = "14" // 自动采集的非机动车辆信息
	SubscribeDetailTypeItem15 SubscribeDetailTypeItem = "15" // 自动采集的物品信息
	SubscribeDetailTypeItem16 SubscribeDetailTypeItem = "16" // 自动采集的文件信息
)

type (
	DirectionType      string
	HDirectionType     DirectionType
	HorizontalShotType DirectionType
)

const (
	DirectionType1 DirectionType = "1" // 西向东（简称东，下同）
	DirectionType2 DirectionType = "2" // 东向西（西）
	DirectionType3 DirectionType = "3" // 北向南（南）
	DirectionType4 DirectionType = "4" // 南向北（北）
	DirectionType5 DirectionType = "5" // 西南到东北（东北）
	DirectionType6 DirectionType = "6" // 东北到西南（西南）
	DirectionType7 DirectionType = "7" // 西北到东南（东南）
	DirectionType8 DirectionType = "8" // 东南到西北（西北）
	DirectionType9 DirectionType = "9" // 其他
)

// VerticalShotType 垂直拍摄方向
type VerticalShotType string

const (
	VerticalShotType1 VerticalShotType = "1" // 上
	VerticalShotType2 VerticalShotType = "2" // 水平
	VerticalShotType3 VerticalShotType = "3" // 下
)

// TollgateType string(2) 卡口类型 10，国际; 20，省际; 30，市际; 31，市区; 40，县际; 41，县区; 99，其他;
type TollgateType string

const (
	TollgateType10 TollgateType = "10" // 国际
	TollgateType20 TollgateType = "20" // 省际
	TollgateType30 TollgateType = "30" // 市际
	TollgateType31 TollgateType = "31" // 市区
	TollgateType40 TollgateType = "40" // 县际
	TollgateType41 TollgateType = "41" // 县区
)

// Boolean 二值逻辑
type Boolean string

const (
	BooleanFalse Boolean = "0" // 否，无， false， 离线等否定状态
	BooleanTrue  Boolean = "1" // 是，有， true，在线等肯定状态
)

// PlateClassType 号牌种类
type PlateClassType string

const (
	PlateClassType01 PlateClassType = "01" // 大型汽车号牌
	PlateClassType02 PlateClassType = "02" // 小型汽车号牌
	PlateClassType03 PlateClassType = "03" // 使馆汽车号牌
	PlateClassType04 PlateClassType = "04" // 领馆汽车号牌
	PlateClassType05 PlateClassType = "05" // 境外汽车号牌
	PlateClassType06 PlateClassType = "06" // 外籍汽车号牌
	PlateClassType07 PlateClassType = "07" // 普通摩托车号牌
	PlateClassType08 PlateClassType = "08" // 轻便摩托车号牌
	PlateClassType09 PlateClassType = "09" // 使馆摩托车号牌
	PlateClassType10 PlateClassType = "10" // 领馆摩托车号牌
	PlateClassType11 PlateClassType = "11" // 境外摩托车号牌
	PlateClassType12 PlateClassType = "12" // 外籍摩托车号
	PlateClassType13 PlateClassType = "13" // 低速车号牌
	PlateClassType14 PlateClassType = "14" // 拖拉机号牌
	PlateClassType15 PlateClassType = "15" // 挂车号牌
	PlateClassType16 PlateClassType = "16" // 教练汽车号牌
	PlateClassType17 PlateClassType = "17" // 教练摩托车号牌
	PlateClassType20 PlateClassType = "20" // 临时入境汽车号牌
	PlateClassType21 PlateClassType = "21" // 临时入境摩托车号牌
	PlateClassType22 PlateClassType = "22" // 临时行驶车号牌
	PlateClassType23 PlateClassType = "23" // 警用汽车号牌
	PlateClassType24 PlateClassType = "24" // 警用摩托车号牌
	PlateClassType25 PlateClassType = "25" // 原农机号牌
	PlateClassType26 PlateClassType = "26" // 香港入出境号牌
	PlateClassType27 PlateClassType = "27" // 澳门入出境号牌
	PlateClassType31 PlateClassType = "31" // 武警号牌
	PlateClassType32 PlateClassType = "32" // 军队号牌
	PlateClassType99 PlateClassType = "99" // 其他号牌
)

// IdNumberType 证件号码
type IdNumberType string

// IDType 证件类型
type IDType string

const (
	IDType111 IDType = "111" // 居民身份证
	IDType113 IDType = "114" // 军官证
	IDType123 IDType = "123" // 警官证
	IDType414 IDType = "414" // 普通护照
)

// StatusType 视频设备工作状态: 1在线 2离线 9其他
type StatusType string

const (
	StatusType1 StatusType = "1" // 在线
	StatusType2 StatusType = "2" // 离线
	StatusType9 StatusType = "9" // 其他
)

// DataSourceType 视频图像数据来源
type DataSourceType string

const (
	DataSourceType1  DataSourceType = "1"  // 政府机关监控
	DataSourceType2  DataSourceType = "2"  // 社会面治安监控
	DataSourceType3  DataSourceType = "3"  // 交通监控（含轨道交通监控）
	DataSourceType4  DataSourceType = "4"  // 出入境监控
	DataSourceType5  DataSourceType = "5"  // 港口监控
	DataSourceType6  DataSourceType = "6"  // 金融系统监控
	DataSourceType7  DataSourceType = "7"  // 旅馆监控
	DataSourceType8  DataSourceType = "8"  // 互联网营业场所监控
	DataSourceType9  DataSourceType = "9"  // 娱乐服务场所监控
	DataSourceType10 DataSourceType = "10" // 其他企业/事业单位监控
	DataSourceType11 DataSourceType = "11" // 居民自建监控
	DataSourceType12 DataSourceType = "12" // 公安内部
	DataSourceType13 DataSourceType = "13" // 监所
	DataSourceType14 DataSourceType = "14" // 讯问室
	DataSourceType15 DataSourceType = "15" // 车（船、直升机等）载终端拍摄
	DataSourceType16 DataSourceType = "16" // 移动执法
	DataSourceType17 DataSourceType = "17" // 手机、平板电脑拍摄
	DataSourceType18 DataSourceType = "18" // DV 拍摄
	DataSourceType19 DataSourceType = "19" // 相机拍摄
	DataSourceType20 DataSourceType = "20" // 网络获取
	DataSourceType21 DataSourceType = "21" // 声像资料片
	DataSourceType99 DataSourceType = "99" // 其他
)

// EventType 视频图像分析处理事件类型
type EventType int

const (
	EventType0  EventType = 0  // 其他
	EventType1  EventType = 1  // 卡口 过车
	EventType2  EventType = 2  // 卡口 过人
	EventType3  EventType = 3  // 卡口 打架
	EventType4  EventType = 4  // 卡口 快速奔跑
	EventType5  EventType = 5  // 目标检测与特征提取 运动目标检测
	EventType6  EventType = 6  // 目标检测与特征提取 目标分类
	EventType7  EventType = 7  // 目标检测与特征提取 目标颜色检测
	EventType8  EventType = 8  // 目标检测与特征提取 行人检测
	EventType9  EventType = 9  // 目标检测与特征提取 人员属性分析
	EventType10 EventType = 10 //  目标检测与特征提取 人脸检测
	EventType11 EventType = 11 //  目标检测与特征提取 人脸比对
	EventType12 EventType = 12 //  目标检测与特征提取 车辆检测
	EventType13 EventType = 13 //  目标检测与特征提取 车辆比对
	EventType14 EventType = 14 //  目标数量分析 流量统计
	EventType15 EventType = 15 //  目标数量分析 密度检测
	EventType16 EventType = 16 //  目标识别 车牌识别
	EventType17 EventType = 17 //  目标识别 车辆基本特征识别
	EventType18 EventType = 18 //  目标识别 车辆个体特征识别
	EventType19 EventType = 19 //  行为分析 绊线检测
	EventType20 EventType = 20 //  行为分析 入侵检测
	EventType21 EventType = 21 //  行为分析 逆行检测
	EventType22 EventType = 22 //  行为分析 徘徊检测
	EventType23 EventType = 23 //  行为分析 遗留物检测
	EventType24 EventType = 24 //  行为分析 目标移除检测
	EventType25 EventType = 25 //  视频摘要 视频摘要
	EventType26 EventType = 26 //  视频增强与复原 去雾
	EventType27 EventType = 27 //  视频增强与复原 去模糊
	EventType28 EventType = 28 //  视频增强与复原 对比度增强
	EventType29 EventType = 29 //  视频增强与复原 低照度视频图像增强
	EventType30 EventType = 30 //  视频增强与复原 偏色校正
	EventType31 EventType = 31 //  视频增强与复原 宽动态增强
	EventType32 EventType = 32 //  视频增强与复原 超分辨率重建
	EventType33 EventType = 33 //  视频增强与复原 几何畸变校正
	EventType34 EventType = 34 //  视频增强与复原 奇偶场校正
	EventType35 EventType = 35 //  视频增强与复原 颜色空间分量分离
	EventType36 EventType = 36 //  视频增强与复原 去噪声
)

// ImageFormatType string(5) 图片格式
type ImageFormatType string

const (
	ImageFormatTypeBmp   ImageFormatType = "Bmp"   //  BMP
	ImageFormatTypeGif   ImageFormatType = "Gif"   //  GIF
	ImageFormatTypeJpeg  ImageFormatType = "Jpeg"  //  JPEG
	ImageFormatTypeJfif  ImageFormatType = "Jfif"  //  JFIF
	ImageFormatTypeKdc   ImageFormatType = "Kdc"   //  KDC
	ImageFormatTypePcd   ImageFormatType = "Pcd"   //  PCD
	ImageFormatTypePcx   ImageFormatType = "Pcx"   //  PCX
	ImageFormatTypePic   ImageFormatType = "Pic"   //  PIC
	ImageFormatTypePix   ImageFormatType = "Pix"   //  PIX
	ImageFormatTypePng   ImageFormatType = "Png"   //  PNG
	ImageFormatTypePsd   ImageFormatType = "Psd"   //  PSD
	ImageFormatTypeTapga ImageFormatType = "Tapga" //  TAPGA
	ImageFormatTypeTiff  ImageFormatType = "Tiff"  //  TIFF
	ImageFormatTypeWmf   ImageFormatType = "Wmf"   //  WMF
	ImageFormatTypeJp2   ImageFormatType = "Jp2"   //  JPEG 2000
	ImageFormatTypeOther ImageFormatType = "Other" //  其他
)

// SecretLevelType 密级代码
type SecretLevelType string

const (
	SecretLevelType1 SecretLevelType = "1" // 绝密
	SecretLevelType2 SecretLevelType = "2" // 机密
	SecretLevelType3 SecretLevelType = "3" // 秘密
	SecretLevelType4 SecretLevelType = "4" // 内部
	SecretLevelType5 SecretLevelType = "5" // 公开
	SecretLevelType9 SecretLevelType = "9" // 其他
)

// VideoFormatType 视频格式 string(6)
type VideoFormatType string

const (
	VideoFormatTypeMpg   VideoFormatType = "Mpg"   //   MPG
	VideoFormatTypeMov   VideoFormatType = "Mov"   //   MOV
	VideoFormatTypeAvi   VideoFormatType = "Avi"   //   AVI
	VideoFormatTypeRm    VideoFormatType = "Rm"    //    RM
	VideoFormatTypeRmvb  VideoFormatType = "Rmvb"  //  RMVB
	VideoFormatTypeFlv   VideoFormatType = "Flv"   //   FLV
	VideoFormatTypeVob   VideoFormatType = "Vob"   //   VOB
	VideoFormatTypeM2ts  VideoFormatType = "M2ts"  //   M2TS
	VideoFormatTypeMp4   VideoFormatType = "Mp4"   //   MP4
	VideoFormatTypeEs    VideoFormatType = "Es"    //    ES
	VideoFormatTypePs    VideoFormatType = "Ps"    //    PS
	VideoFormatTypeTs    VideoFormatType = "Ts"    //    TS 文件
	VideoFormatTypeOther VideoFormatType = "Other" // 其他
)

type (
	AudioCodeFormatType string // string(2) 音频编码格式
	VideoCodeFormatType string // string(2) 视频编码格式
)

const (
	AudioCodeFormatType1  AudioCodeFormatType = "1"  // G.711
	AudioCodeFormatType2  AudioCodeFormatType = "2"  // G.723
	AudioCodeFormatType3  AudioCodeFormatType = "3"  // G.729
	AudioCodeFormatType99 AudioCodeFormatType = "99" // 其他
)
const (
	VideoCodeFormatTypeSVAC  VideoCodeFormatType = "1"  // SVAC
	VideoCodeFormatTypeH264  VideoCodeFormatType = "2"  // H.264
	VideoCodeFormatTypeMPEG4 VideoCodeFormatType = "3"  // MPEG-4
	VideoCodeFormatTypeMPEG2 VideoCodeFormatType = "4"  // MPEG-2
	VideoCodeFormatTypeMJPEG VideoCodeFormatType = "5"  // MJPEG
	VideoCodeFormatTypeH263  VideoCodeFormatType = "6"  // H.263
	VideoCodeFormatTypeH265  VideoCodeFormatType = "7"  // H.265
	VideoCodeFormatTypeOther VideoCodeFormatType = "99" //  其他
)

// QualityGradeType 质量等级
type QualityGradeType string

const (
	QualityGradeType1 QualityGradeType = "1" // 极差
	QualityGradeType2 QualityGradeType = "2" // 较差
	QualityGradeType3 QualityGradeType = "3" // 一般
	QualityGradeType4 QualityGradeType = "4" // 较好
	QualityGradeType5 QualityGradeType = "5" // 很好
)

// ImageType 图像类型
type ImageType string

const (
	ImageType01  ImageType = "01"  // 车辆大图
	ImageType02  ImageType = "02"  // 车牌彩色小图
	ImageType03  ImageType = "03"  // 车牌二值化图
	ImageType04  ImageType = "04"  // 驾驶员面部特征图
	ImageType05  ImageType = "05"  // 副驾驶面部特征图
	ImageType06  ImageType = "06"  // 车标
	ImageType07  ImageType = "07"  // 违章合成图
	ImageType08  ImageType = "08"  // 过车合成图
	ImageType09  ImageType = "09"  // 车辆特写图
	ImageType10  ImageType = "10"  // 人员图
	ImageType11  ImageType = "11"  // 人脸图
	ImageType12  ImageType = "12"  // 非机动车图
	ImageType13  ImageType = "13"  // 物品图
	ImageType14  ImageType = "14"  // 场景图
	ImageType100 ImageType = "100" //  一般图片
)

func (d DeviceIDType) String() string {
	return string(d)
}

// TypeCode APE: 119, APS: 120
func (d DeviceIDType) TypeCode() string {
	resourceID := string(d)
	switch len(resourceID) {
	case 20, 41, 48:
		typeCode := resourceID[10:13]
		return typeCode
	default:
		return ""
	}
}

func (d DeviceIDType) IsAPS() bool {
	code := d.TypeCode()
	return code == "120" || code == "503"
}

func (d DeviceIDType) IsAPE() bool {
	return d.TypeCode() == "119"
}

func (d BasicObjectIdType) String() string {
	return string(d)
}

func (d ImageCntObjectIdType) String() string {
	return string(d)
}
